home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
-
- /* Tom Davis -- 1992 */
-
- /* This code takes a solid defined by quadrilaterals, finds those
- * with similar coordinates, and constructs normal vectors by averaging
- * the normals to the individual quads meeting at the point. The
- * routines count on having the floating point values exactly equal --
- * it doesn't do a "within epsilon" test. To use it, make sure that
- * any points at common vertices have EXACTLY the same floating point
- * coordinates. All (well, at least most) of the code in this directory
- * satisfies those conditions.
- */
-
- #include <stdio.h>
- #include "3d.h"
-
- #define CHUNKCOUNT 500
-
- typedef struct chunklist {
- struct chunklist *next;
- long *data;
- } chunklist_t;
-
- chunklist_t *chunklist = 0;
-
- static long *addchunks(long length)
- {
- chunklist_t *c = (chunklist_t *)malloc(sizeof(chunklist_t));
- long i, *l;
-
- c->next = chunklist;
- chunklist = c;
- c->data = l = (long *)malloc(4*length*CHUNKCOUNT);
- for (i = 0; i < CHUNKCOUNT-2; i++)
- l[i*length] = (long)&l[(i+1)*length];
- l[(CHUNKCOUNT-2)*length] = 0;
- return l;
- }
-
- static void freechunkdata()
- {
- chunklist_t *c;
-
- while (c = chunklist) {
- free(c->data);
- chunklist = c->next;
- free(c);
- }
- }
-
- typedef struct polylist {
- struct polylist *next;
- long data;
- } polylist_t;
-
- typedef struct vertex3d {
- struct vertex3d *next;
- float v[3];
- float n[3]; /* averaged normal */
- polylist_t *polys;
- } vertex3d_t;
-
- typedef struct quad {
- struct quad *next;
- struct vertex3d *v0, *v1, *v2, *v3;
- float n[3];
- } quad_t;
-
- #define VERTHASHSIZE 1693
-
- vertex3d_t *verthashtab[VERTHASHSIZE];
- quad_t *quadlist = 0;
-
- static long hashvert(float v[3])
- {
- long h;
-
- h = (*(long *)&v[0]) + ((*(long *)&v[1])>>1) + ((*(long *)&v[2])>>5);
- h &= 0x7ffffff;
- h = h % VERTHASHSIZE;
- return h;
- }
-
- vertex3d_t *vlist = 0;
-
- static vertex3d_t *newvertex3d()
- {
- vertex3d_t *v;
-
- if (vlist == 0) vlist = (vertex3d_t *)addchunks((sizeof(vertex3d_t))>>2);
- v = vlist;
- vlist = vlist->next;
- v->next = 0;
- v->polys = 0;
- return v;
- }
-
- quad_t *qlist = 0;
-
- static quad_t *newquad()
- {
- quad_t *q;
-
- if (qlist == 0) qlist = (quad_t *)addchunks((sizeof(quad_t))>>2);
- q = qlist;
- qlist = qlist->next;
- q->next = quadlist;
- quadlist = q;
- return q;
- }
-
- polylist_t *plist = 0;
-
- static polylist_t *newpolylist()
- {
- polylist_t *p;
-
- if (plist == 0) plist = (polylist_t *)addchunks((sizeof(polylist_t))>>2);
- p = plist;
- plist = plist->next;
- return p;
- }
-
- static vertex3d_t *findverthash(float v[3])
- {
- long h = hashvert(v);
- vertex3d_t *vt;
-
- vt = verthashtab[h];
-
- while (vt) {
- if (vt->v[0] == v[0] && vt->v[1] == v[1] && vt->v[2] == v[2])
- return vt;
- vt = vt->next;
- }
- return 0;
- }
-
- static void appendpoly(long p, vertex3d_t *v)
- {
- polylist_t *pl = newpolylist();
-
- pl->data = p;
- pl->next = v->polys;
- v->polys = pl;
- }
-
- static vertex3d_t *addvertex(float v[3])
- {
- vertex3d_t *vt = newvertex3d();
- long h = hashvert(v);
-
- vt->v[0] = v[0]; vt->v[1] = v[1]; vt->v[2] = v[2];
- vt->next = verthashtab[h];
- verthashtab[h] = vt;
- return vt;
- }
-
- static void cleanupsmooth()
- {
- long i;
-
- freechunkdata();
- for (i = 0; i < VERTHASHSIZE; i++) verthashtab[i] = 0;
- chunklist = 0;
- quadlist = 0;
- qlist = 0;
- vlist = 0;
- plist = 0;
- }
-
- void addquad(float v0[3], float v1[3], float v2[3], float v3[3], float n[3])
- {
- quad_t *q = newquad();
- vertex3d_t *v;
-
- q->n[0] = n[0]; q->n[1] = n[1]; q->n[2] = n[2];
- if (0 == (v = findverthash(v0)))
- v = addvertex(v0);
- q->v0 = v;
- appendpoly((long)q, v);
- if (0 == (v = findverthash(v1)))
- v = addvertex(v1);
- q->v1 = v;
- appendpoly((long)q, v);
- if (0 == (v = findverthash(v2)))
- v = addvertex(v2);
- q->v2 = v;
- appendpoly((long)q, v);
- if (0 == (v = findverthash(v3)))
- v = addvertex(v3);
- q->v3 = v;
- appendpoly((long)q, v);
- }
-
- void doverts()
- {
- long i;
- vertex3d_t *vt;
- polylist_t *p;
- quad_t *q;
- float v[3];
- long vcount;
-
- for (i = 0; i < VERTHASHSIZE; i++) {
- vt = verthashtab[i];
- while (vt) {
- p = (polylist_t *)vt->polys;
- v[0] = v[1] = v[2] = 0.0; vcount = 0;
- while (p) {
- q = (quad_t *)p->data;
- v[0] += q->n[0]; v[1] += q->n[1]; v[2] += q->n[2]; vcount++;
- p = p->next;
- }
- if (v[0] != 0.0 || v[1] != 0.0 || v[2] != 0.0) {
- normalize(v);
- } else v[0] =1.0; /* XXX hack! XXX */
- vt->n[0] = v[0]; vt->n[1] = v[1]; vt->n[2] = v[2];
- vt = vt->next;
- }
- }
- }
-
- void doquads(void (*savefunc)())
- {
- quad_t *q = quadlist;
-
- while (q) {
- savefunc(ADD_QUAD, q->v0->n, q->v0->v, q->v1->n, q->v1->v,
- q->v2->n, q->v2->v, q->v3->n, q->v3->v);
- q = q->next;
- }
- cleanupsmooth();
- }
-
-